原题传送门 —>>

给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。

按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:

“123”
“132”
“213”
“231”
“312”
“321”
给定 n 和 k,返回第 k 个排列。

说明:

给定 n 的范围是 [1, 9]。
给定 k 的范围是[1, n!]。

示例 1:

输入: n = 3, k = 3
输出: “213”

示例 2:

输入: n = 4, k = 9
输出: “2314”


容易想到的是深搜(回溯),但 O(n!)的复杂度可以直接判死刑了。(但是我看题解里确实回溯+剪枝过了的)
下面的是种偏向数学的解法。

思路:

  • 对于4个数字(1,2,3,4),1开头的序列有3! 、即6个,2开头的同理,那么假如要求第15个,那么一定是3((15-1)除以6 再加1)开头
  • 继续,3已经确定是第一个数字,剩下的数字有1,2,4。我们接下来需要求1、3、4全排列的第3((15-1) mod 6)个数字,规则同上,则需要以第2(3除以2再加1)个数字开头, 2是第二个数字
  • 同上,1是第3个数字,4是第4个数字
  • 答案为3214

15 - 1 = 6 × 2 + 2 × 1 + 1 × 0
(6、2、1分别是3、2、1的阶乘),每次取第3、2、1 个数字(剩下一个数字自动补上就可以)
100% kill代码:

class Solution {
public:
    string getPermutation(int n, int k) {
     vector<int> a;
     vector<int> b;
    for(int i = 1; i <= n; ++i)
        b.push_back(i);
    a.push_back(1);
    for(int i = 2; i < n; ++i)
    {
        a.push_back(a[i-2]*i);
    }
    int kk = k - 1;
    string ans;
    for(int i = 0; i < n-1; ++i)
    {
        int j = kk/a[n-2-i];
        kk %= a[n-2-i];
        ans.push_back(b[j] + '0');
        b.erase(b.begin()+ j);
    }
        ans.push_back(b[0] + '0');
        return ans;
    }
};